package com.xingfei.blog.service;

import com.alibaba.dubbo.common.json.JSON;
import com.alibaba.dubbo.common.utils.CollectionUtils;
import com.alibaba.dubbo.common.utils.StringUtils;
import com.xingfei.blog.constants.ErrorConstants;
import com.xingfei.blog.constants.GeneralConstants;
import com.xingfei.blog.constants.RedisConstants;
import com.xingfei.blog.dto.*;
import com.xingfei.blog.enums.BannerEnableTypeEnum;
import com.xingfei.blog.enums.BannerTypeEnum;
import com.xingfei.blog.enums.CommentTypeEnum;
import com.xingfei.blog.redisCluster.RedisClusterUtil;
import com.xingfei.blog.redisCluster.dao.RedisClusterDao;
import com.xingfei.blog.result.ServiceResult;
import com.xingfei.blog.utils.DESUtil;
import com.xingfei.blog.utils.HTMLUtils;
import com.xingfei.blog.utils.IPUtil;
import com.xingfei.blog.vo.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

import static com.xingfei.blog.constants.RedisConstants.ARTICLE_IS_COLLECTED_FOR_USER;
import static com.xingfei.blog.constants.RedisConstants.ARTICLE_IS_PARISED_FOR_USER;

/**
 * Created by Administrator on 2017/2/18.
 */
@Service("webArticleService")
public class WebArticleService {

    /**
     * 日志
     */
    public static final Logger LOGGER = LoggerFactory.getLogger(WebArticleService.class);
    @Autowired
    private BlogArticleService blogArticleService;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private BlogUserService blogUserService;
    @Autowired
    private WebUserService webUserService;
    @Autowired
    private BlogUserAttentionService blogUserAttentionService;
    @Autowired
    private RedisClusterDao redisClusterDao;
    @Autowired
    private WebCommentService webCommentService;
    @Autowired
    private WebBannerService webBannerService;
    /**
     * 图片访问域名获取
     */
    @Value("${jianyi.imageDomainUrl}")
    private String imageDomainUrl;

    /**
     * 根据id查询用户信息
     *
     * @param articleId 文章id
     * @param userId    用户id
     * @return
     */
    public ArticleVo findArticleById(Long articleId, Long userId) {
        // 更新当前文章查看次数
        String articleViewCountKey = MessageFormat.format(RedisConstants.ARTICLE_VIEW_COUNT, articleId);
        if (redisClusterDao.isExist(articleViewCountKey)) {
            redisClusterDao.incr(articleViewCountKey);
        } else {
            redisClusterDao.set(articleViewCountKey, "1", 0L);
        }
        ServiceResult<ArticleDTO> serviceResult = this.blogArticleService.getArticleById(articleId);
        if (serviceResult != null && serviceResult.getCode() == ErrorConstants.RES_SUCCESS) {
            ArticleDTO articleTO = serviceResult.getResult();
            // 转换数据
            if (articleTO != null) {
                ArticleVo articleVo = new ArticleVo();
                BeanUtils.copyProperties(articleTO, articleVo);
                if (articleTO.getArticleContentDTO() != null) {
                    ArticleContentVO articleContentVO = new ArticleContentVO();
                    BeanUtils.copyProperties(articleTO.getArticleContentDTO(), articleContentVO);
                    articleVo.setArticleContentVO(articleContentVO);
                }
                if (articleTO.getUserId() != null) {
                    //封装文章发布者信息
                    articleVo.setUserVO(webUserService.getUserAndUserInfoById(articleTO.getUserId()));
                }
                //获取当前登录用户是否关注当前文章发布作者
                if (userId != null) {
                    UserAttentionDTO userAttentionDto = new UserAttentionDTO();
                    userAttentionDto.setAttentionId(userId);
                    userAttentionDto.setByAttentionId(articleVo.getUserId());
                    ServiceResult<UserAttentionDTO> result = this.blogUserAttentionService.getAttentionByAttentionIdAndBeAttentionId(userAttentionDto);
                    if (result != null && result.getCode() == ErrorConstants.RES_SUCCESS) {
                        articleVo.setAttention(true);
                    }
                }
                //获取当前文章的评论列表
                UserCommentVO userCommentVo = new UserCommentVO();
                userCommentVo.setRelativeId(articleId);
                userCommentVo.setType(CommentTypeEnum.COMMENT_ARTICLE.ordinal());
                List<UserCommentVO> listUserComments = this.webCommentService.listUserComments(userCommentVo, 1, 3);
                if (CollectionUtils.isNotEmpty(listUserComments)) {
                    articleVo.setUserCommentVOS(listUserComments);
                }

                return articleVo;
            }
        }
        return null;
    }

    /**
     * 组装首页数据，包含用户数据，用户粉丝数，关注数，文章列表
     *
     * @param userDTO
     * @return
     */
    public UserVO buildDataForUser(UserDTO userDTO) {
        UserVO userVO = new UserVO();
        appendUserInfo(userDTO, userVO);
        return null;
    }

    /**
     * 组装文章数据
     *
     * @param articleDTO
     * @param page
     * @param pageSize
     * @return
     */
//    @Cacheable(value = "listByPageWeb", key = "'listByPageNew:'+#page.toString()")
    public List<ArticleVo> listByPage(ArticleDTO articleDTO, Integer page, Integer pageSize) {
        //根据条件查询文章列表
        try {
            ServiceResult<List<ArticleDTO>> listArticles = this.blogArticleService.listByPageNew(articleDTO, page, pageSize);
            List<ArticleVo> articleVos = buildArticleData(listArticles);
        } catch (Exception e) {
            LOGGER.error(">>>>>>>>>>>>>分页获取文章列表失败,msg={}", e.toString());
            e.printStackTrace();
        }
        return null;
    }
    /** 
     * @Desc 获取我收藏的文章
     * @author chenxingfei
     * @methodName  listColletionArticleFormeByPage
     * @date 2017/7/15 11:56
     * @param collectionVO
     * @param page 当前页
     * @param pageSize 查询数据条数
     */
    public List<ArticleVo> listColletionArticleFormeByPage(CollectionVO collectionVO, Integer page, Integer pageSize) {
        //根据条件查询文章列表
        try {
            CollectionDTO collectionDTO = new CollectionDTO();
            BeanUtils.copyProperties(collectionVO,collectionDTO);
            ServiceResult<List<ArticleDTO>> listArticles = this.blogArticleService.listColletionArticleFormeByPage(collectionDTO,page,pageSize);
            List<ArticleVo> articleVos = buildArticleData(listArticles);
            if (articleVos != null) return articleVos;
        } catch (Exception e) {
            LOGGER.error(">>>>>>>>>>>>>分页获取文章列表失败,msg={}", e.toString());
            e.printStackTrace();
        }
        return null;
    }

    /**
     * dubbo服务返回数据处理
     * @param listArticles
     * @return
     */
    private List<ArticleVo> buildArticleData(ServiceResult<List<ArticleDTO>> listArticles) {
        if (listArticles != null && listArticles.getCode() == ErrorConstants.RES_SUCCESS) {
            List<ArticleDTO> result = listArticles.getResult();
            if (CollectionUtils.isNotEmpty(result)) {
                List<ArticleVo> articleVos = new ArrayList<>();
                result.forEach(action -> {
                    ArticleVo articleVo = new ArticleVo();
                    BeanUtils.copyProperties(action, articleVo);
                    //处理首页文章显示字数
                    String acticleContent = action.getDescription();
                    if (StringUtils.isNotEmpty(acticleContent)) {
                        if (acticleContent.length() > 100) {
                            acticleContent = acticleContent.substring(0, 100) + "...";
                        }
                    }
                    articleVo.setDescription(acticleContent);
                    articleVos.add(articleVo);
                });
                return articleVos;
            }
        }
        return null;
    }

    /**
     * 封裝用戶信息
     *
     * @param articleVo
     */
    public void appendUserInfo(ArticleVo articleVo) {
        ServiceResult<UserDTO> userByIdResult = this.blogUserService.getUserById(articleVo.getUserId());
        if (userByIdResult != null && userByIdResult.getCode() == ErrorConstants.RES_SUCCESS) {
            UserDTO userDTO = userByIdResult.getResult();
            if (userDTO != null) {
                UserVO userVO = new UserVO();
                UserInfoVO userInfoVO = new UserInfoVO();
                BeanUtils.copyProperties(userDTO, userVO);
                BeanUtils.copyProperties(userDTO.getUserInfoDTO(), userInfoVO);
                if (StringUtils.isNotEmpty(userInfoVO.getAvatarUrl()) && !userInfoVO.getAvatarUrl().startsWith("http")) {
                    userInfoVO.setAvatarUrl(imageDomainUrl + userInfoVO.getAvatarUrl());
                }
                userVO.setUserInfoVO(userInfoVO);
                articleVo.setUserVO(userVO);
            }
        }
    }

    /**
     * 封装文章其他数据
     *
     * @param articleVo
     * @param userVO    当前登录用户
     */
    public void appendArticleOtherData(ArticleVo articleVo, UserVO userVO) {
        String articleCollectKey = MessageFormat.format(RedisConstants.ARTICLE_COLLECT_COUNT, articleVo.getId());
        String articleCommenttKey = MessageFormat.format(RedisConstants.ARTICLE_COMMENT_COUNT, articleVo.getId());
        String articleViewCountKey = MessageFormat.format(RedisConstants.ARTICLE_VIEW_COUNT, articleVo.getId());
        String articlePariseCountKey = MessageFormat.format(RedisConstants.ARTICLE_PARISE_COUNT, articleVo.getId());
        // 根据当前用户是否登录判断用户是否收藏文章或者点过赞
        if (userVO != null) {
            String isCollectedForUser = MessageFormat.format(ARTICLE_IS_COLLECTED_FOR_USER, userVO.getId(), articleVo.getId());
            if (redisClusterDao.isExist(isCollectedForUser)) {
                articleVo.setCollected(true);
            }
            String isParisedForUser = MessageFormat.format(ARTICLE_IS_PARISED_FOR_USER, userVO.getId(), articleVo.getId());
            if (redisClusterDao.isExist(isParisedForUser)) {
                String parisedId = redisClusterDao.get(isParisedForUser);
                if (parisedId == null) {
                    articleVo.setParisedId(Long.parseLong(parisedId));
                }
                articleVo.setPraised(true);
            }
        }
        if (redisClusterDao.isExist(articleCollectKey)) {
            String collect = redisClusterDao.get(articleCollectKey);
            if (StringUtils.isNotEmpty(collect)) {
                articleVo.setCollectCount(Integer.parseInt(collect));
            }
        } else {
            redisClusterDao.set(articleCollectKey, "1", 0L);
        }
        if (redisClusterDao.isExist(articlePariseCountKey)) {
            String parise = redisClusterDao.get(articlePariseCountKey);
            if (StringUtils.isNotEmpty(parise)) {
                articleVo.setParisedCount(Integer.parseInt(parise));
            }
        } else {
            redisClusterDao.set(articlePariseCountKey, "1", 0L);
        }
        if (redisClusterDao.isExist(articleCommenttKey)) {
            String comment = redisClusterDao.get(articleCommenttKey);
            if (StringUtils.isNotEmpty(comment)) {
                articleVo.setCommentCount(Integer.parseInt(comment));
            }
        } else {
            redisClusterDao.set(articleCommenttKey, "1", 0L);
        }
        if (redisClusterDao.isExist(articleViewCountKey)) {
            String view = redisClusterDao.get(articleViewCountKey);
            if (StringUtils.isNotEmpty(view)) {
                articleVo.setViewCount(Integer.parseInt(view));
            }
        } else {
            redisClusterDao.set(articleViewCountKey, "1", 0L);
        }
    }

    /**
     * 组装用户数据
     *
     * @param userDTO
     * @param userVO
     */
    private void appendUserInfo(UserDTO userDTO, UserVO userVO) {
        userVO.setEmail(userDTO.getEmail());
        userVO.setPhone(userDTO.getPhone());
        userVO.setId(userDTO.getId());
//        stringRedisTemplate.boundValueOps("").
        userVO.setAttentions(0);
        userVO.setBeAttentions(10);
    }


    /**
     * 写文章
     *
     * @param article
     * @return
     */
    public boolean writeArticle(String article, HttpServletRequest request, UserVO userVO) {
        try {
            //解密
            article = DESUtil.decryption(article, GeneralConstants.DES_DECODE_BOLG_PUBLISH_KEY);
            ArticleVo articleVo = JSON.parse(article, ArticleVo.class);
            articleVo.setUserId(userVO.getId());
            if (articleVo != null) {
                articleVo.setArticleIp(IPUtil.getIpAddr(request));
                ArticleDTO articleDTO = new ArticleDTO();
                BeanUtils.copyProperties(articleVo, articleDTO);
                if (articleVo.getArticleContentVO() != null) {
                    if (StringUtils.isNotEmpty(articleVo.getArticleContentVO().getActicleContent())) {
                        String delHTMLTagStr = HTMLUtils.delHTMLTag(articleVo.getArticleContentVO().getActicleContent());
                        if (StringUtils.isNotEmpty(delHTMLTagStr)) {
                            if (delHTMLTagStr.length() > 100) {
                                articleDTO.setDescription(delHTMLTagStr.substring(0, 100) + "...");
                            } else {
                                articleDTO.setDescription(delHTMLTagStr);
                            }
                        }
                    }
                    ArticleContentDTO articleContentDTO = new ArticleContentDTO();
                    BeanUtils.copyProperties(articleVo.getArticleContentVO(), articleContentDTO);
                    articleDTO.setArticleContentDTO(articleContentDTO);
                }
                ServiceResult<ArticleDTO> serviceResult = this.blogArticleService.saveArticle(articleDTO);
                if (serviceResult != null && serviceResult.getCode() == ErrorConstants.RES_SUCCESS) {
                    return true;
                }
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
}
